<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Parallel_Serial.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Reads in a data word, sends it out serially, bit by bit (MSB first), and signals when the final bit is out and a new data word can be read-in, in the same cycle if necessary to create an uninterrupted serial stream.">
<title>Parallel Serial</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Parallel_Serial.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Parallel to Serial Converter</h1>
<p>Reads in a data word, sends it out serially, bit by bit (MSB first), and
 signals when the final bit is out and a new data word can be read-in, in
 the same cycle if necessary to create an uninterrupted serial stream.</p>
<p>When the <code>parallel_in</code> ready/valid handshakes completes, <code>parallel_in</code> is
 loaded, <code>parallel_in_ready</code> goes low while the bits shift out (MSB first),
 and goes back high once the last loaded bit appears at <code>serial_out</code>,
 allowing a simultanous reload for a continuous stream of serial bits to be
 sent.</p>
<p>Otherwise, if no new word is loaded, the shifter halts (holding the last
 bit steady at <code>serial_out</code>, and <code>parallel_in_ready</code> goes high, awaiting the
 next load.</p>
<p>Holding <code>clock_enable</code> low halts any shifting, holding all bits in place
 and ignoring any changes at the control and data inputs, <em>except for
 <code>clear</code></em>.</p>
<p>Asserting <code>clear</code> will empty the shift register, zero-out the counter,
 raise <code>parallel_in_ready</code>, and halt all activity until the next ready/valid
 handshake.</p>

<pre>
`default_nettype none

module <a href="./Parallel_Serial.html">Parallel_Serial</a>
#(
    parameter WORD_WIDTH = 0
)
(
    input   wire                        clock,
    input   wire                        clock_enable,
    input   wire                        clear,

    input   wire                        parallel_in_valid,
    output  reg                         parallel_in_ready,
    input   wire    [WORD_WIDTH-1:0]    parallel_in,

    output  wire                        serial_out
);

    `include "<a href="./clog2_function.html">clog2_function</a>.vh"

    localparam WORD_ZERO   = {WORD_WIDTH{1'b0}};
    localparam COUNT_WIDTH = clog2(WORD_WIDTH);
    localparam COUNT_ZERO  = {COUNT_WIDTH{1'b0}};
    localparam COUNT_BITS  = WORD_WIDTH - 1; 

    initial begin
        parallel_in_ready = 1'b1; // We start empty, so ready to load.
    end
</pre>

<p>Count the number of bit shifts remaning, starting at WORD_WIDTH-1 since the
 first bit is immediately visible at <code>serial_out</code> after a load.  When the
 last bit is visible at <code>serial_out</code>, the count reaches zero, the counter
 halts, and we can immediately load a new word.</p>

<pre>
    reg                     counter_run  = 1'b0;
    reg                     counter_load = 1'b0;
    wire [COUNT_WIDTH-1:0]  count;

    <a href="./Counter_Binary.html">Counter_Binary</a>
    #(
        .WORD_WIDTH     (COUNT_WIDTH),
        .INCREMENT      (1),
        .INITIAL_COUNT  (COUNT_ZERO)
    )
    shifts_remaining
    (
        .clock          (clock),
        .clear          (clear),
        .up_down        (1'b1), // 0 up, 1 down
        .run            (counter_run),
        .load           (counter_load),
        .load_count     (COUNT_BITS [COUNT_WIDTH-1:0]),
        .carry_in       (1'b0),
        // verilator lint_off PINCONNECTEMPTY
        .carry_out      (),
        .carries        (),
        .overflow       (),
        // verilator lint_on  PINCONNECTEMPTY
        .count          (count)
    );
</pre>

<p>The shift register only shifts when the counter is running.</p>

<pre>
    reg shifter_run  = 1'b0;
    reg shifter_load = 1'b0;

    <a href="./Register_Pipeline.html">Register_Pipeline</a>
    #(
        .WORD_WIDTH     (1),
        .PIPE_DEPTH     (WORD_WIDTH),
        .RESET_VALUES   (WORD_ZERO)
    )
    shift_register
    (
        .clock          (clock),
        .clock_enable   (shifter_run),
        .clear          (clear),
        .parallel_load  (shifter_load),
        .parallel_in    (parallel_in),
        // verilator lint_off PINCONNECTEMPTY
        .parallel_out   (),
        // verilator lint_on  PINCONNECTEMPTY
        .pipe_in        (1'b0),
        .pipe_out       (serial_out)
    );
</pre>

<p>Completing the parallel input handshake both loads the data word into the
 shift register and loads the counter with the pipeline depth (minus 1),
 starting the bit shifting.  After all the bits have appeared at
 <code>serial_out</code>, the counter reaches to zero, halts, and raises
 <code>parallel_in_ready</code>.</p>

<pre>
    reg handshake_done = 1'b0;

    always @(*) begin
        parallel_in_ready   = (count == COUNT_ZERO) && (clock_enable == 1'b1);
        handshake_done      = (parallel_in_valid == 1'b1) && (parallel_in_ready == 1'b1);

        counter_run         = (count != COUNT_ZERO) && (clock_enable == 1'b1);
        counter_load        = (handshake_done == 1'b1);

        shifter_run         = (counter_run == 1'b1) || (counter_load == 1'b1);
        shifter_load        = (counter_load == 1'b1);
    end

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

